package com.slh.touchandroid.fragment;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import android.R.dimen;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.AlertDialog.Builder;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.support.v4.app.DialogFragment;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.slh.touchandroid.R;
import com.slh.touchandroid.model.AppInfo;
import com.slh.touchandroid.utils.AppUtils;
import com.stericson.RootTools.RootTools;

public class InstalledAppFragment extends BaseFragment implements
		OnItemClickListener {
	// ======================================================================
	private static final int REQUEST_UNINSTALL_APP = 1000;
	private static final int MENU_ID_LAUNCH_AP = 0;
	private static final int MENU_ID_UNINSTALL_AP = MENU_ID_LAUNCH_AP + 1;
	private static final int MENU_ID_2_SYS_AP = MENU_ID_LAUNCH_AP + 2;
	private static final int MENU_ID_2_USER_AP = MENU_ID_LAUNCH_AP + 3;
	private static final int MENU_ID_2_SDCARD = MENU_ID_LAUNCH_AP + 4;
	private ArrayList<AppInfo> mApplicationInfos;
	private InstalledAppAdapter mAppAdapter;
	private ListView mAppListView;
	private int mItemPosition = 0;

	// ======================================================================
	@Override
	public void onCreate(Bundle savedInstanceState) {
		setRetainInstance(true);
		setHasOptionsMenu(true);
		super.onCreate(savedInstanceState);
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View rootView = inflater.inflate(R.layout.fragment_list, container,
				false);
		mAppListView = (ListView) rootView
				.findViewWithTag(getString(R.string.tag_list));
		registerForContextMenu(mAppListView);
		loadApps(AppUtils.FILTER_ALL_APPS);
		return rootView;
	}

	@Override
	public void onDestroyView() {
		unregisterForContextMenu(mAppListView);
		super.onDestroyView();
	}

	@Override
	public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
		inflater.inflate(R.menu.app, menu);
		super.onCreateOptionsMenu(menu, inflater);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.action_filter_all_app:
			loadApps(AppUtils.FILTER_ALL_APPS);
			break;
		case R.id.action_filter_system_app:
			loadApps(AppUtils.FILTER_SYSTEMS_APPS);
			break;
		case R.id.action_filter_user_app:
			loadApps(AppUtils.FILTER_USER_APPS);
			break;

		default:
			break;
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		int position = ((AdapterContextMenuInfo) menuInfo).position;
		AppInfo appInfo = mApplicationInfos.get(position);
		menu.add(0, MENU_ID_LAUNCH_AP, 0, R.string.lauch_app);
		menu.add(0, MENU_ID_UNINSTALL_AP, 1, R.string.uninstall_app);
		if (appInfo.isSystemApp) {
			menu.add(0, MENU_ID_2_USER_AP, 2, R.string.convert_to_user_app);
		} else {
			menu.add(0, MENU_ID_2_SYS_AP, 2, R.string.convert_to_system_app);
		}
		super.onCreateContextMenu(menu, v, menuInfo);
	}

	@Override
	public boolean onContextItemSelected(MenuItem item) {
		AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item
				.getMenuInfo();
		AppInfo info = mApplicationInfos.get(menuInfo.position);
		switch (item.getItemId()) {
		case MENU_ID_LAUNCH_AP:
			// TODO
			// TEST
			AppUtils.launchApp(getActivity(), info.pgk);
			// Intents.showPackageDetail(getActivity(), info.pgk);
			break;
		case MENU_ID_UNINSTALL_AP:
			mItemPosition = menuInfo.position;
			if (info.isSystemApp) {
				if (!RootTools.isRootAvailable()) {
					Toast.makeText(getActivity(), "Root Require",
							Toast.LENGTH_SHORT).show();
					break;
				}
				if (!RootTools.isBusyboxAvailable()) {
					Toast.makeText(getActivity(), "Busybox not available",
							Toast.LENGTH_SHORT).show();
					break;
				}
				if (!RootTools.deleteFileOrDirectory(info.srcDir, true)) {
					Toast.makeText(getActivity(), "Please try again later",
							Toast.LENGTH_SHORT).show();
				}
			} else {
				AppUtils.uninstallAppWithResult(getActivity(), info.pgk,
						REQUEST_UNINSTALL_APP);
			}

			break;
		case MENU_ID_2_SYS_AP:
			mItemPosition = menuInfo.position;
			if (!RootTools.isRootAvailable()) {
				Toast.makeText(getActivity(), "Root Require",
						Toast.LENGTH_SHORT).show();
				break;
			}
			if (!RootTools.isBusyboxAvailable()) {
				Toast.makeText(getActivity(), "Busybox not available",
						Toast.LENGTH_SHORT).show();
				break;
			}
			boolean copy = RootTools.copyFile(info.srcDir, "/system/app", true,
					true);
			if (!copy) {
				Toast.makeText(getActivity(), "Please try again later",
						Toast.LENGTH_SHORT).show();

			}
			RootTools.deleteFileOrDirectory(info.srcDir, true);

			showRestartDialog();
			break;
		case MENU_ID_2_USER_AP:
			mItemPosition = menuInfo.position;
			if (!RootTools.isRootAvailable()) {
				Toast.makeText(getActivity(), "Root Require",
						Toast.LENGTH_SHORT).show();
				break;
			}
			if (!RootTools.isBusyboxAvailable()) {
				Toast.makeText(getActivity(), "Busybox not available",
						Toast.LENGTH_SHORT).show();
				break;
			}
			if (!RootTools.copyFile(info.srcDir, "/data/app", true, true)) {
				Toast.makeText(getActivity(), "Please try again later",
						Toast.LENGTH_SHORT).show();

			}
			RootTools.deleteFileOrDirectory(info.srcDir, true);
			showRestartDialog();
			break;
		default:
			break;
		}
		return super.onContextItemSelected(item);
	}

	// ===================================================================
	private void loadApps(int filter) {
		new AsyncTask<Integer, Void, ArrayList<AppInfo>>() {
			private ProgressDialog dialog;

			protected void onPreExecute() {
				dialog = new ProgressDialog(getActivity());
				dialog.show();
			};

			@Override
			protected ArrayList<AppInfo> doInBackground(Integer... params) {
				List<ApplicationInfo> infos = AppUtils.getInstalledApplication(
						getActivity(), params[0]);
				ArrayList<AppInfo> apps = new ArrayList<AppInfo>();
				for (ApplicationInfo applicationInfo : infos) {
					apps.add(new AppInfo(
							applicationInfo.packageName,
							AppUtils.getApplicationLabel(getActivity(),
									applicationInfo),
							AppUtils.getApplicationIcon(getActivity(),
									applicationInfo),
							(applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0,
							applicationInfo.sourceDir));
				}
				Collections.sort(apps, new Comparator<AppInfo>() {

					@Override
					public int compare(AppInfo lhs, AppInfo rhs) {
						return lhs.name.compareTo(rhs.name);
					}
				});

				return apps;
			}

			@Override
			protected void onPostExecute(ArrayList<AppInfo> result) {
				if (null != dialog && dialog.isShowing()) {
					dialog.dismiss();
				}
				mApplicationInfos = result;
				mAppAdapter = new InstalledAppAdapter(getActivity(),
						mApplicationInfos);
				mAppListView.setAdapter(mAppAdapter);
				mAppListView.setOnItemClickListener(InstalledAppFragment.this);
				super.onPostExecute(result);
			}
		}.execute(filter);
	}

	// ===================================================================
	private static class Holder {
		TextView tvName;
		TextView tvDesc;
	}

	// ===================================================================
	private static class InstalledAppAdapter extends BaseAdapter {
		private Context context;
		private ArrayList<AppInfo> applications;

		public InstalledAppAdapter(Context context,
				ArrayList<AppInfo> applications) {
			super();
			this.context = context;
			this.applications = applications;
		}

		@Override
		public int getCount() {
			return applications.size();
		}

		@Override
		public Object getItem(int position) {
			return applications.get(position);
		}

		@Override
		public long getItemId(int position) {
			return position;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			Holder holder;
			if (null == convertView) {
				convertView = LayoutInflater.from(context).inflate(
						R.layout.row_common, null);
				holder = new Holder();
				holder.tvName = (TextView) convertView.findViewWithTag(context
						.getString(R.string.tag_name));
				holder.tvDesc = (TextView) convertView.findViewWithTag(context
						.getString(R.string.tag_desc));
				convertView.setTag(holder);
			} else {
				holder = (Holder) convertView.getTag();
			}
			AppInfo application = applications.get(position);
			holder.tvName.setText(application.name);
			Drawable icon = application.icon;
			icon.setBounds(0, 0, 48, 48);
			holder.tvName.setCompoundDrawables(icon, null, null, null);
			if (application.isSystemApp) {
				holder.tvDesc.setVisibility(View.VISIBLE);
			} else {
				holder.tvDesc.setVisibility(View.GONE);
			}
			return convertView;
		}

	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		switch (requestCode) {
		case REQUEST_UNINSTALL_APP:
			if (resultCode != Activity.RESULT_OK) {
				return;
			}
			mApplicationInfos.remove(mItemPosition);
			mAppAdapter.notifyDataSetChanged();
			break;

		default:
			break;
		}
		super.onActivityResult(requestCode, resultCode, data);
	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position,
			long id) {
		getActivity().openContextMenu(view);

	}

	private void showRestartDialog() {
		DialogFragment dialogFragment = new DialogFragment() {
			@Override
			public View onCreateView(LayoutInflater inflater,
					ViewGroup container, Bundle savedInstanceState) {
				View rootView = inflater.inflate(R.layout.view_restart_dialog,
						container, false);
				final TextView timer = (TextView) rootView
						.findViewWithTag(getString(R.string.tag_text));
				CountDownTimer countDownTimer = new CountDownTimer(5000, 1000) {

					@Override
					public void onTick(long millisUntilFinished) {
						timer.setText((millisUntilFinished) / 1000 + " (s)");

					}

					@Override
					public void onFinish() {
						timer.setText("0 (s)");
						RootTools.restartAndroid();

					}
				};
				countDownTimer.start();

				return rootView;
			}

			@Override
			public Dialog onCreateDialog(Bundle savedInstanceState) {
				Dialog dialog = super.onCreateDialog(savedInstanceState);
				dialog.setTitle("Restart");
				return dialog;
			}
		};
		dialogFragment.show(getFragmentManager(), "");
	}

}
